﻿using SuperSocialShare.Error;
using SuperSocialShare.Helper;
using SuperSocialShare.Authorize;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text.RegularExpressions;

namespace SuperSocialShare.Clients
{
    public class SinaClient : SocialClient
    {

        protected override string AuthorizeUrl
        {
            get { return "https://open.weibo.cn/oauth2/authorize"; }
        }

        protected override string GetAccessTokenUrl
        {
            get { return "https://api.weibo.com/oauth2/access_token"; }
        }

        protected override string GetUserInfoUrl
        {
            get { return "https://api.weibo.com/2/users/show.json"; }
        }

        protected override string RevokeAuthorizeUrl
        {
            get { return "https://api.weibo.com/oauth2/revokeoauth2"; }
        }

        protected override string UpdateStatusUrl
        {
            get { return "https://api.weibo.com/2/statuses/update.json"; }
        }

        protected override string UploadImageUrl
        {
            get { return "https://upload.api.weibo.com/2/statuses/upload.json"; }
        }


        public override SocialType SocialType
        {
            get { return SocialType.Sina; }
        }


        /// <summary>
        /// 获取请求OAuth授权地址
        /// </summary>
        /// <returns></returns>
        internal override string GetRequestAuthorizeUrl()
        {
            Dictionary<string, object> parameters = new Dictionary<string, object>() 
            {
                {"client_id",ClientId},
                {"client_secret",ClientSecret},
                {"display","mobile"},
                {"response_type","code"},
                {"redirect_uri",CallbackUrl}
            };
            return Utility.BuildQueryString(AuthorizeUrl, parameters);
        }

        /// <summary>
        /// 使用code方式获取AccessToken
        /// </summary>
        /// <param name="code">获取授权码需要提供的Code</param>
        protected override void GetAccessTokenAsync(string code)
        {
            Dictionary<string, object> parameters = new Dictionary<string, object>() 
            {
                {"client_id",ClientId},
                {"client_secret",ClientSecret},
                {"grant_type","authorization_code"},
                {"code",code},
                {"redirect_uri",CallbackUrl}
            };
            String queryStr = Utility.BuildQueryString(GetAccessTokenUrl, parameters);
            HttpWebRequester requester = new HttpWebRequester();
            requester.RequestCompleted += requester_RequestCompleted;
            requester.BeginRequest(queryStr, 0, "POST");
        }

        protected override void GetUserInfoAsync(AuthorizeInfo info)
        {
            HttpWebRequester requester = new HttpWebRequester();
            requester.Parameters.Add(new RequestParameter("access_token", info.AccessToken));
            requester.Parameters.Add(new RequestParameter("uid", info.UserID));
            requester.RequestCompleted += requester_RequestCompleted;
            requester.BeginRequest(GetUserInfoUrl, 1);
        }

        public override void RevokeAuthorizeAysnc()
        {
            SinaAuthorizeInfo info = AuthorizeManager.GetAuthorizeInfo(SocialType) as SinaAuthorizeInfo;
            if (info != null)
            {

                Dictionary<string, object> parameters = new Dictionary<string, object>() 
            {
                {"access_token",info.AccessToken},
            };
                string queryStr = Utility.BuildQueryString(RevokeAuthorizeUrl, parameters);
                HttpWebRequester requester = new HttpWebRequester();
                requester.RequestCompleted += requester_RequestCompleted;
                requester.BeginRequest(queryStr, 3);
            }
        }

        /// <summary>
        /// 处理请求授权后的返回数据，新浪网的返回数据为authorize_code
        /// </summary>
        /// <param name="data"></param>
        internal override void ProcessResponseDataOfAuthorize(string data)
        {
            string code = Utility.GetRegexContent(@"(?<=code=)[^&]*", data);
            HttpWebRequester requester = new HttpWebRequester();
            requester.Parameters.Add(new RequestParameter("client_id", ClientId));
            requester.Parameters.Add(new RequestParameter("client_secret", ClientSecret));
            requester.Parameters.Add(new RequestParameter("grant_type", "authorization_code"));
            requester.Parameters.Add(new RequestParameter("code", code));
            requester.Parameters.Add(new RequestParameter("redirect_uri", CallbackUrl));
            requester.RequestCompleted += requester_RequestCompleted;
            requester.BeginRequest(GetAccessTokenUrl, 0, "POST");
        }

        /// <summary>
        /// 分享文字
        /// </summary>
        /// <param name="text">要分享的文本</param>
        public override void ShareText(string text)
        {
            SinaAuthorizeInfo info = AuthorizeManager.GetAuthorizeInfo(SocialType) as SinaAuthorizeInfo;
            if (info != null)
            {
                HttpWebRequester requester = new HttpWebRequester();
                requester.PostContentType = ContentType.APPLICATION_X_WWW_FORM_URLENCODED;
                requester.Parameters.Add(new RequestParameter("access_token", info.AccessToken));
                requester.Parameters.Add(new RequestParameter("status", HttpUtility.UrlEncode(text)));
                requester.RequestCompleted += requester_RequestCompleted;
                requester.BeginRequest(UpdateStatusUrl, 2, "POST");
            }
        }

        /// <summary>
        /// 上传图片并发布一条微博
        /// </summary>
        /// <param name="text">要发布的文本</param>
        /// <param name="imgdata">上传图片的二进制数据</param>
        public override void ShareTextWithImage(string text, byte[] imgdata)
        {
            SinaAuthorizeInfo info = AuthorizeManager.GetAuthorizeInfo(SocialType) as SinaAuthorizeInfo;
            if (info != null)
            {
                HttpWebRequester requester = new HttpWebRequester();
                requester.PostContentType = ContentType.MULTIPART_FORM_DATA;
                requester.Parameters.Add(new RequestParameter("access_token", info.AccessToken));
                requester.Parameters.Add(new RequestParameter("status", HttpUtility.UrlEncode(text)));
                requester.Parameters.Add(new RequestParameter("pic", imgdata));
                requester.RequestCompleted += requester_RequestCompleted;
                requester.BeginRequest(UploadImageUrl, 2, "POST");
            }
        }


        void requester_RequestCompleted(RequestCompletedEventArgs e)
        {
            AsyncEventArgs args = new AsyncEventArgs();
            int actionTag = Convert.ToInt32(e.UserData);
            if (e.Error == null)
            {
                SinaError error = JsonConverter.GetObjectFromJsonString(e.Result, typeof(SinaError)) as SinaError;
                if (error != null && error.ErrorCode != 0)
                    args.Error = error;

                switch (actionTag)
                {
                    case 0://获取的数据授权信息
                        if (args.Error != null)//发生错误，触发事件授权结束事件
                        {
                            OnGetAuthorizeInfoCompleted(args);
                        }
                        else//如果未发生错误，继续获取用户信息
                        {
                            SinaAuthorizeInfo aInfo = JsonConverter.GetObjectFromJsonString(e.Result, typeof(SinaAuthorizeInfo)) as SinaAuthorizeInfo;
                            if (aInfo != null)
                            {
                                args.Result = aInfo;
                                AuthorizeManager.Save(aInfo, SocialType);
                                GetUserInfoAsync(aInfo);
                            }
                        }
                        break;

                    case 1://获取的数据为用户信息
                        if (args.Error == null)
                        {
                            UserInfo userInfo = new UserInfo();
                            userInfo.Fill(e.Result, SocialType);
                            SinaAuthorizeInfo authorizeInfo = AuthorizeManager.GetAuthorizeInfo(SocialType) as SinaAuthorizeInfo;
                            authorizeInfo.UserInfo = userInfo;
                            args.Result = authorizeInfo;
                        }
                        OnGetAuthorizeInfoCompleted(args);
                        break;

                    case 2://数据为分享文字后的返回信息
                        OnShareCompleted(args);
                        break;

                    case 3://数据为取消授权后返回信息
                        SinaRevokeAuthorizeResult result = JsonConverter.GetObjectFromJsonString(e.Result, typeof(SinaRevokeAuthorizeResult)) as SinaRevokeAuthorizeResult;
                        if (result.IsSuccess)
                        {
                            AuthorizeManager.DeleteAuthorizeInfo(SocialType);
                        }
                        OnRevokeAuthorizeCompleted(result);
                        break;
                    default:
                        break;
                }
            }
            else
            {
                args.Error = new ErrorBase(e.Error);
                switch (actionTag)
                {
                    case 0:
                    case 1://获取授权过程中发生网络错误
                        OnGetAuthorizeInfoCompleted(args);
                        break;
                    case 2://分享过程中发生网络错误
                        OnShareCompleted(args);
                        break;
                    case 3:
                        SinaRevokeAuthorizeResult result = new SinaRevokeAuthorizeResult();
                        result.IsSuccess = false;
                        OnRevokeAuthorizeCompleted(result);
                        break;
                    default:
                        break;
                }
            }
        }
    }
}
